#include <exception>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>

#include "server.h"
#include "log.h"
#include "pidfile.h"
#include "qworker.h"


int main(int argc, char* argv[])
{
    
    if (!g_config.parse_config(argc, argv, std::cout))
    {
        return 200;
    }
    
    if (!g_config.m_foreground)
    {
        if (daemon(0, 0) < 0)
        {
        	perror("Can't demonize !");
    	    exit(3);
        }
    }

    g_log.initlog("asudserver", 9999);
    boost::thread log(boost::bind(&logger::run, &g_log));
    
    try
    {
		g_log.msg(MSG_NORMAL, "Start process...");

		sigset_t new_mask;
		sigfillset(&new_mask);
		sigset_t old_mask;
		pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);

		server s(g_config.m_listen_point, g_config.m_worker_count, g_config.m_uid, g_config.m_gid );
		
		g_worker.init_worker(&s.network_, &s.sqlhandle_);
		boost::thread w(boost::bind(&qworker::run, &g_worker));
		

		boost::thread t(boost::bind(&server::run, &s));

		if (!g_pid_file.create(g_config.m_pid_file))
		{
			g_log.msg(MSG_NORMAL,boost::format("Can't write PID file: name='%s', error='%s'") % g_config.m_pid_file % strerror(errno));
		}

		while(true)
		{
			pthread_sigmask(SIG_SETMASK, &old_mask, 0);

			sigset_t wait_mask;
			sigemptyset(&wait_mask);
			sigaddset(&wait_mask, SIGINT);
			sigaddset(&wait_mask, SIGQUIT);
			sigaddset(&wait_mask, SIGTERM);
//				sigaddset(&wait_mask, SIGHUP);
			pthread_sigmask(SIG_BLOCK, &wait_mask, 0);
			int sig = 0;

			sigwait(&wait_mask, &sig);

			g_log.msg(MSG_NORMAL, boost::format("Received signal: %d, exiting...") % sig);

			break;
		}

		g_worker.stop();
		w.join();

		s.stop();
		t.join();

		g_log.msg(MSG_NORMAL, "Normal end process...");

    }
    catch (const std::exception &e)
    {
    	g_log.msg(MSG_NORMAL, boost::format("Can't start server process: %d") % e.what());
    	std::cout << e.what() << std::endl;
    }
    
    g_pid_file.unlink();
    
    g_log.stop();
    log.join();
    
    return 0;
}
